home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / daemons / lpd / recvjob.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-08-16  |  6.6 KB  |  327 lines

  1. /*
  2.  * Copyright (c) 1983 Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms are permitted
  6.  * provided that this notice is preserved and that due credit is given
  7.  * to the University of California at Berkeley. The name of the University
  8.  * may not be used to endorse or promote products derived from this
  9.  * software without specific prior written permission. This software
  10.  * is provided ``as is'' without express or implied warranty.
  11.  */
  12.  
  13. #ifndef lint
  14. static char sccsid[] = "@(#)recvjob.c    5.6 (Berkeley) 5/5/88";
  15. #endif /* not lint */
  16.  
  17. /*
  18.  * Receive printer jobs from the network, queue them and
  19.  * start the printer daemon.
  20.  */
  21.  
  22. #include "lp.h"
  23. #ifndef sprite
  24. #include <sys/fs.h>
  25. #endif
  26.  
  27. char    *sp = "";
  28. #define ack()    (void) write(1, sp, 1);
  29.  
  30. char    tfname[40];        /* tmp copy of cf before linking */
  31. char    dfname[40];        /* data files */
  32. int    minfree;        /* keep at least minfree blocks available */
  33. char    *ddev;            /* disk device (for checking free space) */
  34. int    dfd;            /* file system device descriptor */
  35.  
  36. char    *find_dev();
  37.  
  38. recvjob()
  39. {
  40.     struct stat stb;
  41.     char *bp = pbuf;
  42.     int status, rcleanup();
  43.  
  44.     /*
  45.      * Perform lookup for printer name or abbreviation
  46.      */
  47.     if ((status = pgetent(line, printer)) < 0)
  48.         frecverr("cannot open printer description file");
  49.     else if (status == 0)
  50.         frecverr("unknown printer %s", printer);
  51.     if ((LF = pgetstr("lf", &bp)) == NULL)
  52.         LF = DEFLOGF;
  53.     if ((SD = pgetstr("sd", &bp)) == NULL)
  54.         SD = DEFSPOOL;
  55.     if ((LO = pgetstr("lo", &bp)) == NULL)
  56.         LO = DEFLOCK;
  57.  
  58.     (void) close(2);            /* set up log file */
  59.     if (open(LF, O_WRONLY|O_APPEND, 0664) < 0) {
  60.         syslog(LOG_ERR, "%s: %m", LF);
  61.         (void) open("/dev/null", O_WRONLY);
  62.     }
  63.  
  64.     if (chdir(SD) < 0)
  65.         frecverr("%s: %s: %m", printer, SD);
  66.     if (stat(LO, &stb) == 0) {
  67.         if (stb.st_mode & 010) {
  68.             /* queue is disabled */
  69.             putchar('\1');        /* return error code */
  70.             exit(1);
  71.         }
  72.     } else if (stat(SD, &stb) < 0)
  73.         frecverr("%s: %s: %m", printer, SD);
  74. #ifndef sprite
  75.     minfree = read_number("minfree");
  76.     ddev = find_dev(stb.st_dev, S_IFBLK);
  77.     if ((dfd = open(ddev, O_RDONLY)) < 0)
  78.         syslog(LOG_WARNING, "%s: %s: %m", printer, ddev);
  79. #else
  80.     /*
  81.      * Should have similar thing to check for free space...
  82.      */
  83. #endif
  84.     signal(SIGTERM, rcleanup);
  85.     signal(SIGPIPE, rcleanup);
  86.  
  87.     if (readjob())
  88.         printjob();
  89. }
  90.  
  91. #ifndef sprite
  92. char *
  93. find_dev(dev, type)
  94.     register dev_t dev;
  95.     register int type;
  96. {
  97.     register DIR *dfd = opendir("/dev");
  98.     struct direct *dir;
  99.     struct stat stb;
  100.     char devname[MAXNAMLEN+6];
  101.     char *dp;
  102.  
  103.     strcpy(devname, "/dev/");
  104.     while ((dir = readdir(dfd))) {
  105.         strcpy(devname + 5, dir->d_name);
  106.         if (stat(devname, &stb))
  107.             continue;
  108.         if ((stb.st_mode & S_IFMT) != type)
  109.             continue;
  110.         if (dev == stb.st_rdev) {
  111.             closedir(dfd);
  112.             dp = (char *)malloc(strlen(devname)+1);
  113.             strcpy(dp, devname);
  114.             return(dp);
  115.         }
  116.     }
  117.     closedir(dfd);
  118.     frecverr("cannot find device %d, %d", major(dev), minor(dev));
  119.     /*NOTREACHED*/
  120. }
  121. #endif /* sprite */
  122.  
  123. /*
  124.  * Read printer jobs sent by lpd and copy them to the spooling directory.
  125.  * Return the number of jobs successfully transfered.
  126.  */
  127. readjob()
  128. {
  129.     register int size, nfiles;
  130.     register char *cp;
  131.  
  132.     ack();
  133.     nfiles = 0;
  134.     for (;;) {
  135.         /*
  136.          * Read a command to tell us what to do
  137.          */
  138.         cp = line;
  139.         do {
  140.             if ((size = read(1, cp, 1)) != 1) {
  141.                 if (size < 0)
  142.                     frecverr("%s: Lost connection",printer);
  143.                 return(nfiles);
  144.             }
  145.         } while (*cp++ != '\n');
  146.         *--cp = '\0';
  147.         cp = line;
  148.         switch (*cp++) {
  149.         case '\1':    /* cleanup because data sent was bad */
  150.             rcleanup();
  151.             continue;
  152.  
  153.         case '\2':    /* read cf file */
  154.             size = 0;
  155.             while (*cp >= '0' && *cp <= '9')
  156.                 size = size * 10 + (*cp++ - '0');
  157.             if (*cp++ != ' ')
  158.                 break;
  159.             /*
  160.              * host name has been authenticated, we use our
  161.              * view of the host name since we may be passed
  162.              * something different than what gethostbyaddr()
  163.              * returns
  164.              */
  165.             strcpy(cp + 6, from);
  166.             strcpy(tfname, cp);
  167.             tfname[0] = 't';
  168.             if (!chksize(size)) {
  169.                 (void) write(1, "\2", 1);
  170.                 continue;
  171.             }
  172.             if (!readfile(tfname, size)) {
  173.                 rcleanup();
  174.                 continue;
  175.             }
  176.             if (link(tfname, cp) < 0)
  177.                 frecverr("%s: %m", tfname);
  178.             (void) unlink(tfname);
  179.             tfname[0] = '\0';
  180.             nfiles++;
  181.             continue;
  182.  
  183.         case '\3':    /* read df file */
  184.             size = 0;
  185.             while (*cp >= '0' && *cp <= '9')
  186.                 size = size * 10 + (*cp++ - '0');
  187.             if (*cp++ != ' ')
  188.                 break;
  189.             if (!chksize(size)) {
  190.                 (void) write(1, "\2", 1);
  191.                 continue;
  192.             }
  193.             strcpy(dfname, cp);
  194.             (void) readfile(dfname, size);
  195.             continue;
  196.         }
  197.         frecverr("protocol screwup");
  198.     }
  199. }
  200.  
  201. /*
  202.  * Read files send by lpd and copy them to the spooling directory.
  203.  */
  204. readfile(file, size)
  205.     char *file;
  206.     int size;
  207. {
  208.     register char *cp;
  209.     char buf[BUFSIZ];
  210.     register int i, j, amt;
  211.     int fd, err;
  212.  
  213.     fd = open(file, O_WRONLY|O_CREAT, FILMOD);
  214.     if (fd < 0)
  215.         frecverr("%s: %m", file);
  216.     ack();
  217.     err = 0;
  218.     for (i = 0; i < size; i += BUFSIZ) {
  219.         amt = BUFSIZ;
  220.         cp = buf;
  221.         if (i + amt > size)
  222.             amt = size - i;
  223.         do {
  224.             j = read(1, cp, amt);
  225.             if (j <= 0)
  226.                 frecverr("Lost connection");
  227.             amt -= j;
  228.             cp += j;
  229.         } while (amt > 0);
  230.         amt = BUFSIZ;
  231.         if (i + amt > size)
  232.             amt = size - i;
  233.         if (write(fd, buf, amt) != amt) {
  234.             err++;
  235.             break;
  236.         }
  237.     }
  238.     (void) close(fd);
  239.     if (err)
  240.         frecverr("%s: write error", file);
  241.     if (noresponse()) {        /* file sent had bad data in it */
  242.         (void) unlink(file);
  243.         return(0);
  244.     }
  245.     ack();
  246.     return(1);
  247. }
  248.  
  249. noresponse()
  250. {
  251.     char resp;
  252.  
  253.     if (read(1, &resp, 1) != 1)
  254.         frecverr("Lost connection");
  255.     if (resp == '\0')
  256.         return(0);
  257.     return(1);
  258. }
  259.  
  260. /*
  261.  * Check to see if there is enough space on the disk for size bytes.
  262.  * 1 == OK, 0 == Not OK.
  263.  */
  264. chksize(size)
  265.     int size;
  266. {
  267. #ifndef sprite
  268.     struct stat stb;
  269.     register char *ddev;
  270.     int spacefree;
  271.     struct fs fs;
  272.  
  273.     if (dfd < 0 || lseek(dfd, (long)(SBOFF), 0) < 0)
  274.         return(1);
  275.     if (read(dfd, (char *)&fs, sizeof fs) != sizeof fs)
  276.         return(1);
  277.     spacefree = freespace(&fs, fs.fs_minfree) * fs.fs_fsize / 1024;
  278.     size = (size + 1023) / 1024;
  279.     if (minfree + size > spacefree)
  280.         return(0);
  281. #endif
  282.     return(1);
  283. }
  284.  
  285. read_number(fn)
  286.     char *fn;
  287. {
  288.     char lin[80];
  289.     register FILE *fp;
  290.  
  291.     if ((fp = fopen(fn, "r")) == NULL)
  292.         return (0);
  293.     if (fgets(lin, 80, fp) == NULL) {
  294.         fclose(fp);
  295.         return (0);
  296.     }
  297.     fclose(fp);
  298.     return (atoi(lin));
  299. }
  300.  
  301. /*
  302.  * Remove all the files associated with the current job being transfered.
  303.  */
  304. rcleanup()
  305. {
  306.  
  307.     if (tfname[0])
  308.         (void) unlink(tfname);
  309.     if (dfname[0])
  310.         do {
  311.             do
  312.                 (void) unlink(dfname);
  313.             while (dfname[2]-- != 'A');
  314.             dfname[2] = 'z';
  315.         } while (dfname[0]-- != 'd');
  316.     dfname[0] = '\0';
  317. }
  318.  
  319. frecverr(msg, a1, a2)
  320.     char *msg;
  321. {
  322.     rcleanup();
  323.     syslog(LOG_ERR, msg, a1, a2);
  324.     putchar('\1');        /* return error code */
  325.     exit(1);
  326. }
  327.